package org.yn.gift.service.impl;

import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.yn.gift.client.AuthClient;
import org.yn.gift.constants.BaseConstants;
import org.yn.gift.domain.LoginUser;
import org.yn.gift.domain.User;
import org.yn.gift.domain.UserInfo;
import org.yn.gift.dto.SmsDTO;
import org.yn.gift.dto.UserPhoneRegisterDto;
import org.yn.gift.exception.AssertUtil;
import org.yn.gift.exception.BusinessException;
import org.yn.gift.exception.ResponseCode;
import org.yn.gift.mapper.UserInfoMapper;
import org.yn.gift.mapper.UserMapper;
import org.yn.gift.service.IUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.yn.gift.util.AjaxResult;
import org.yn.gift.util.MD5Utils;
import org.yn.gift.util.StrUtils;

import java.util.Date;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author YN
 * @since 2023-09-12
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
  private   RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private AuthClient authClient;

    @Value("${MD5.preFix}")
    String preFix;

    @Value("${MD5.endFix}")
    String endFix;
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void SendRegisterCode(String phone) {

        // 参数校验
        // phone不能为空   断言
        AssertUtil.isNotBlank(phone, ResponseCode.RESPONSE_CODE_500);

        //验证改手机号的用户是否存在 是否已经注册   TODO
//        User user = userMapper.selectByPhone(dto.getPhone());

        //断言判空      TODO
//        AssertUtil.isNull(user,ResponseCode.RESPONSE_CODE_40018);
        //判断redis中是否有手机验证码  没有则发送
        //redis中key 手机号码+_sms      value为手机验证码:发送时间
        String prefix = BaseConstants.REGISTER_SMS_VERIFY_CODE_KEY;
        sendSms(phone, prefix);
    }

    /**
     * 注册
     * @param dto
     */
    @GlobalTransactional(rollbackFor = Exception.class)
    @Override
    public void registerByPhone(UserPhoneRegisterDto dto) {
     //参数校验
     AssertUtil.isNotBlank(dto.getPhone(),ResponseCode.RESPONSE_CODE_40010);
     AssertUtil.isNotBlank(dto.getPassword(),ResponseCode.RESPONSE_CODE_40010);
     AssertUtil.isNotBlank(dto.getValidateCode(),ResponseCode.RESPONSE_CODE_40010);

     //之前在发送手机验证码时候已经判断过手机号是否在数据存在了，所以就不用再判断了

     //获取redis中的验证码，与前端传入的验证码相比较
        //获取redis中的验证码
        String smsCodeByRedis = (String)redisTemplate.opsForValue().get(BaseConstants.REGISTER_SMS_VERIFY_CODE_KEY + dto.getPhone());
        // 断言是否为空，为空报错，说明没有或者过期
        String[] split = smsCodeByRedis.split(":");
        String smsCodeByRedis1=  split[0];
        AssertUtil.isNotBlank(smsCodeByRedis1, ResponseCode.RESPONSE_CODE_40017);
        // 不为空或者找到验证码后需要判断验证码是否匹配
        System.out.printf("dtoSmsCode："+dto.getValidateCode());
        System.out.printf("smsCodeByRedis："+smsCodeByRedis1);
        AssertUtil.isEqIgnoreCase(dto.getValidateCode(),smsCodeByRedis1,ResponseCode.RESPONSE_CODE_40020);

        //断言后没有问题说明验证码没问题

        //        密码处理
        //盐值
        String salt = UUID.randomUUID().toString();
        //加密
        String password = MD5Utils.encrypByMd5(preFix + salt + dto.getPassword() + endFix);

//      先保存到Autu服务-User表里面（Autu服务） --因为user服务的user表的loginId 是Auth-user的id
//      远程调用LoginClient完成loginUser添加返回loginId
        LoginUser loginUser = new LoginUser();
        loginUser.setUsername(UUID.randomUUID().toString());
        loginUser.setPassword(password);
        loginUser.setTel(dto.getPhone());
        loginUser.setType(1);
        AjaxResult ajaxResult = authClient.addOrUpdate(loginUser);
        Long loginId = Long.valueOf(ajaxResult.getResultObj().toString());

//        保存User注册信息
        User user = new User();
        user.setCreateTime(new Date().getTime());
        user.setPhone(dto.getPhone());
        user.setPassword(password);
        user.setSalt(salt);
        user.setBitState(1L);
        user.setSecLevel(1);
        user.setLoginId(loginId);
        userMapper.insert(user);

//         保存详细信息    userInfo
        UserInfo userInfo = new UserInfo();
        userInfo.setRegTime(new Date().getTime());
        userInfo.setLevel(0);
        userInfo.setGrowScore(0);
        userInfo.setUserId(user.getId());
        userInfoMapper.insert(userInfo);

//        发送成功短信
        // 发短信    由于用的是阿里云的发送短信的根据，发送的短信模板并不能自己定义，需要去申请，这里发送数字做验证
//        SmsDTO smsDTO = new SmsDTO("1234", dto.getPhone());
//        rabbitTemplate.convertAndSend(RegisterNoticeRabbitmqConfig.EXCHANGE_TOPICS_INFORM,"inform.sms",smsDTO);
        String prefix = BaseConstants.REGISTER_SMS_SUCCESS_CODE_KEY;
        sendSms(dto.getPhone(),prefix);

             int i=  1/0;
    }

    /**
     * 提取出发短信的功能
     * @param phone
     * @param prefix
     */
    private void sendSms(String phone, String prefix) {
        String key = prefix+phone;

        String smsCodeByRedis = (String)redisTemplate.opsForValue().get(key);
        //判断存在
        String smsCode = "";   //手机验证码
        if(StringUtils.isNotBlank(smsCodeByRedis)){
            // 如果已存在,判断有没有过重发时间,如果没过重发时间,就返回错误信息,
            // 过了重发时间将验证码重新放入redis并设置过期时间,将验证码重新发给用户
            smsCode = smsCodeByRedis.split(":")[0];
            String sendTime = smsCodeByRedis.split(":")[1];
            // 判断有没有过重发时间
            // 当前时间-发送时间 > 1分钟 过了重发时间   <1分钟 没过重发时间
            if(System.currentTimeMillis() - Long.parseLong(sendTime) < 60*1000){
                throw new BusinessException(ResponseCode.RESPONSE_CODE_40019);
            }
        }else{
            // 如果不存在,重新生成验证码,放入redis中,
            // 设置过期时间,将验证码发送给用户
            //生成4位数的数字随机验证码
            smsCode = StrUtils.getRandomString(4);
        }

        // 将验证码和当前时间存入redis
        String value = smsCode+":"+System.currentTimeMillis();

        redisTemplate.opsForValue().set(key,value,5, TimeUnit.MINUTES);

        // 发送验证码给用户的手机号

//        smsUtils.sendMessage(phone,smsCode);
        System.out.printf("-----短信为-----"+smsCode);

    }
}
